home *** CD-ROM | disk | FTP | other *** search
- { =========================================================================== }
- { Timer55.pas - High resolution timer ver 5.5, 01-15-90 }
- { }
- { A precise 24 hour timer with resolution of 1 micro-second to measure }
- { elapsed time in seconds. }
- { }
- { Public Domain }
- { by Jim LeMay }
- { Eagle Performance Software }
- { P.O. Box 292786 }
- { Lewisville, TX 75029-2786 }
- { (214)-539-7855 }
- { }
- { =========================================================================== }
-
- {$A+,D-,F-,L-,R-,S-}
-
- UNIT TimerH;
-
-
- INTERFACE
-
- type
- StartStop = (Start, Stop, Sync);
-
- var
- t0, { Timer overhead (seconds) }
- t1, { Time at last Start (seconds) }
- t2, { Time at last Stop (seconds) }
- ElapsedTime: real; { Time between last start and last stop. (seconds) }
-
- procedure Timer (SS: StartStop);
-
-
- IMPLEMENTATION
-
- type
- TicksArray = array [1..5] of byte;
-
- var
- PrevExitProc: pointer;
- T1array,T2array: TicksArray;
-
- const
- TicksPerDay = 103090749440.0; { 2^16 * 1573040 DOS timer ticks/day. }
- TicksPerSec = TicksPerDay/86400.0;
-
- procedure SetTimerMode;
- begin
- Inline
- ($B0/$34 { mov al,$34 ; For counter 0, mode 2 }
- /$E6/$43 { out $43,al ; Set timer for input }
- /$EB/$00 { jmp short $0; Null jump }
- /$31/$C0 { xor ax,ax ; Set ax=0 (Max count) }
- /$E6/$40 { out $40,al ; LSB first }
- /$EB/$00 { jmp short $0; Null jump }
- /$E6/$40);{ out $40,al ; MSB second }
- end;
-
- procedure GetTicks (VAR Ticks: TicksArray);
- begin
- Inline(
- $31/$D2/ { xor dx,dx ; Set DX=0 }
- $8E/$C2/ { mov es,dx ; Segment for DOS timer }
- $88/$D0/ { mov al,dl ; 0 to latch counter 0 }
- { ; }
- $FA/ { cli ; Prevent interrupts }
- $26/$8A/$1E/$6C/$04/ { es: mov bl,[$046C] ; Low byte of system timer }
- $26/$8B/$36/$6D/$04/ { es: mov si,[$046D] ; Mid word of system timer }
- $FB/ { sti ; Enable interrupts AFTER OUT }
- { ; Interrupts not enabled yet }
- $E6/$43/ { out $43,al ; Latch timer }
- { ; Now, interrupts enabled }
- { ; Let system clock be updated now }
- $26/$8A/$3E/$6C/$04/ { es: mov bh,[$046C] ; Again copy of the Low byte }
- $B2/$40/ { mov dl,$40 ; Data port for timer }
- $EC/ { in al,dx ; Timer chip LSB }
- $EB/$00/ { jmp short $0 ; Null jump }
- $88/$C1/ { mov cl,al ; Save in CL }
- $EC/ { in al,dx ; Timer chip MSB }
- $88/$C5/ { mov ch,al ; Move in CH }
- $F7/$D1/ { not cx ; Convert count-down to up }
- { ; }
- $80/$FD/$0A/ { cmp ch,10 ; Since system tick <10ms? }
- $D0/$D6/ { rcl dh,1 ; Save copy of CF }
- $28/$DF/ { sub bh,bl ; BH=1 if before<>after }
- $20/$FE/ { and dh,bh ; DH=1 if pending tick INT }
- $00/$F3/ { add bl,dh ; Inc if INT was pending }
- $83/$D6/$00/ { adc si,$0000 ; Just propogate carry bit }
- { ; }
- $C4/$7E/<TICKS/ { les di,[bp+<Ticks] ; Load address of ticks }
- $FC/ { cld ; Set direction forward }
- $89/$C8/ { mov ax,cx ; Move chip timer word }
- $AB/ { stosw ; Store chip timer word }
- $88/$D8/ { mov al,bl ; Move system low byte }
- $AA/ { stosb ; Store system low byte }
- $89/$F0/ { mov ax,si ; Move system mid word }
- $AB); { stosw ; Store system mid word }
- end;
-
- function ArrayToReal (Ticks: TicksArray): real;
- var
- T: record
- B: byte;
- L: longint;
- end absolute Ticks;
- begin
- ArrayToReal := (T.L)*256.0 + T.B;
- end;
-
- procedure Timer;
- begin
- case SS of
- Start: begin
- ElapsedTime := 0;
- GetTicks (T1array)
- end;
- Stop: begin
- GetTicks (T2array);
- t1 := ArrayToReal (T1array); { Convert AFTER the event! }
- t2 := ArrayToReal (T2array);
- if t2<t1 then
- t2 := t2+TicksPerDay;
- ElapsedTime := (t2-t1-t0)/TicksPerSec { units of seconds }
- end;
- Sync: SetTimerMode;
- end;
- end;
-
- procedure TimerInit;
- var
- least: real;
- b: byte;
- begin
- t0 := 0.0; { Initial value to prevent overflow }
- least := 1000000.0; { Initial value that's too high }
- for b:=1 to 10 do
- begin { Check timer overhead by timing }
- Timer (Start); { itself. Do it 10 times to get the }
- Timer (Stop); { least value. }
- t0 := ArrayToReal(T2array) - ArrayToReal(T1array);
- if t0<least then
- least:=t0;
- end;
- t0 := least; { Minimum overhead for timer }
- end;
-
- {$F+}
- procedure ExitTimerH;
- begin
- ExitProc := PrevExitProc;
- { -- Restore default timer mode -- }
- Inline
- ($B0/$36 { mov al,$36 ; For counter 0, mode 3 }
- /$E6/$43 { out $43,al ; Set timer for input }
- /$EB/$00 { jmp short $0; Null jump }
- /$31/$C0 { xor ax,ax ; Set ax=0 (Max count) }
- /$E6/$40 { out $40,al ; LSB first }
- /$EB/$00 { jmp short $0; Null jump }
- /$E6/$40);{ out $40,al ; MSB second }
- end;
- {$F-}
-
- BEGIN
- PrevExitProc := ExitProc;
- ExitProc := @ExitTimerH;
- SetTimerMode;
- TimerInit;
- END.